home *** CD-ROM | disk | FTP | other *** search
/ InfoMagic Internet Tools 1993 July / Internet Tools.iso / RockRidge / info-service / www / src / midaswww-1.0 / midasdeclare.c < prev    next >
Encoding:
C/C++ Source or Header  |  1992-11-16  |  16.2 KB  |  550 lines

  1. #include <Mrm/MrmAppl.h>                        /* Motif Toolkit and MRM */
  2. #include "midaslist.h"
  3. #include "midaserrors.h"
  4. #include "midasoperand.h"
  5. #include "midasconvert.h"
  6. #include <ctype.h>
  7.  
  8. MidasOperand MidasEvaluateExpression();
  9. ConvertBlock *MidasFindStringConverter();
  10.  
  11. struct ActionBlock {
  12.     void (*ActionRtn)();
  13. };
  14.                     
  15. typedef struct ActionBlock ActionBlock;
  16.  
  17.                   
  18. struct ConvertLink {
  19.    List         *CList;
  20.    ConvertBlock *CLink;
  21. };
  22.  
  23. typedef struct ConvertLink ConvertLink;
  24.  
  25. static List TopLevelCommandList;
  26. static List FunctionList;
  27. static List QualifierList;
  28.  
  29. static List *QualifierLists[20];
  30. static List **CurrentQualifierList = QualifierLists;
  31.  
  32. static char *MidasRemoveSpuriousJunk(in)
  33.     char *in;
  34. {
  35. /*
  36.  *   BUG: This should also support {&*aaa}
  37.  */
  38.     int l = strlen(in);
  39.     if (*in == '&') { in++; l--; }
  40.     if (*in == '*') { in++; l--; }
  41.     
  42.     if (*in == '{')
  43.       {
  44.         char *p = strncpy(XtMalloc(l-1),++in,l-2);
  45.         *(p+l-2) = '\0';
  46.         return p;
  47.       }
  48.     else if (l > 3 && strcmp("...",in+l-3) == 0)
  49.       {
  50.         char *p = strncpy(XtMalloc(l-2),in,l-3);
  51.         *(p+l-3) = '\0';
  52.         return p;
  53.       }
  54.     else return XtNewString(in);
  55. }
  56. static char *MidasRestOfLine(i,VerbVector,VerbCount)
  57. int i;
  58. char *VerbVector[];
  59. int VerbCount;
  60. {
  61.     char *p;
  62.     for (p = VerbVector[i]; p < VerbVector[VerbCount-1]; p++) if (*p == '\0') *p = ' ';
  63.     return VerbVector[i];
  64. }
  65. void MidasTokenizeCommand(command,verbVector,verbCount,maxVerbs,delimiters)
  66.     char  *command;
  67.     char  *verbVector[];
  68.     int   *verbCount;
  69.     int   maxVerbs;
  70.     char  *delimiters;
  71. {
  72.     char *p;
  73.     *verbCount = 0;
  74.  
  75.     for (p=command;;)
  76.       {
  77.         int quotes = 0, paren = 0;
  78.         for (; *p == ' '; p++);
  79.         if (*p == '\0') break;
  80.         if (*verbCount == maxVerbs) MidasError("Too many tokens found in line");
  81.         verbVector[(*verbCount)++] = p;
  82.         for (; (paren > 0 || quotes || strchr(delimiters,*p) == 0) && *p != '\0'; p++)
  83.           if      (*p == '"') quotes = !quotes;
  84.           else if (*p == '(') paren++;
  85.           else if (*p == ')') paren--;
  86.         if (*p == '\0') break;
  87.         *p++ = '\0';
  88.       }
  89. }
  90. void MidasDeclareInit()
  91. {
  92.     TopLevelCommandList = NullList;
  93.     FunctionList = NullList;
  94.     QualifierList = NullList;
  95. }
  96. void MidasDeclare(CList,command,ActionRtn,delimiters)
  97.     List *CList;
  98.     char *command;
  99.     void (*ActionRtn)();
  100.     char *delimiters;
  101. {
  102.     ActionBlock *ab;
  103.     ConvertLink *cl;
  104.     ListItem *item;
  105.     int verbCount , i;
  106.     char *verbVector[20];
  107.  
  108.     MidasTokenizeCommand(command,verbVector,&verbCount,
  109.                          XtNumber(verbVector),delimiters);
  110.  
  111.     for (i=0; i < verbCount; i++)
  112.       {
  113.         char *token = verbVector[i];
  114.         Boolean allupper = TRUE; 
  115.         char *p = token;
  116.  
  117.         if (*token == '\0') continue;
  118.  
  119.         for (; *p != '\0'; p++) if (islower(*p)) { allupper = FALSE; break; }
  120.  
  121.         item = MidasFindItemInList(CList,token);
  122.         if (item == 0) 
  123.           {
  124.             item = MidasAddItemToList(CList,token);
  125.             cl = XtNew(ConvertLink);
  126.             item->Pointer = cl;
  127.             cl->CList = MidasCreateEmptyList("");
  128.  
  129.             if (allupper) cl->CLink = 0;
  130.             else
  131.               {
  132.                 MidasType type = MidasRemoveSpuriousJunk(token);
  133.                 cl->CLink = MidasFindStringConverter(type);
  134.                 XtFree(type);
  135.               }
  136.           }
  137.         cl = item->Pointer;
  138.         CList = cl->CList;
  139.       }
  140.  
  141.      item = MidasFindItemInList(CList,"endofcommand");
  142.      if (item == 0) 
  143.        {
  144.          item = MidasAddItemToList(CList,"endofcommand");
  145.          item->Pointer = XtNew(ActionBlock);
  146.        }
  147.      ab = item->Pointer;
  148.      ab->ActionRtn = ActionRtn;
  149. }
  150. void MidasDeclareVerb(command,ActionRtn)
  151.     char *command;
  152.     void (*ActionRtn)();
  153. {
  154.     char *buffer = XtNewString(command);
  155.     MidasDeclare(&TopLevelCommandList,buffer,ActionRtn," ");
  156.     XtFree(buffer);
  157. }
  158. void MidasDeclareFunction(command,ActionRtn)
  159.     char *command;
  160.     void (*ActionRtn)();
  161. {
  162.     char *buffer = XtNewString(command);
  163.     MidasDeclare(&FunctionList,buffer,ActionRtn,"(,)");
  164.     XtFree(buffer);
  165. }
  166. MidasDeclareQualifier(qualifier,type)
  167.      char *qualifier;
  168.      MidasType type;
  169. {
  170.      ListItem *item;
  171.      ConvertBlock *ab,*cab;
  172.  
  173.      item = MidasAddItemToList(&QualifierList,qualifier);
  174.  
  175.      if (*type == '\0') item->Pointer = 0;
  176.      else
  177.        {
  178.          cab = MidasFindStringConverter(type);
  179.          ab = XtNew(ConvertBlock);
  180.          *ab = *cab;
  181.          item->Pointer = ab;
  182.        } 
  183. }
  184. ActionBlock *MidasPrepareToDispatch(CList,command,delimiters,Argv,Argi,ArgC)
  185.      List *CList;
  186.      char *command;
  187.      char *delimiters;
  188.      MidasOperand Argv[10];
  189.      Boolean Argi[10];
  190.      int  *ArgC;
  191. {
  192.      int verbCount , i, Argc = 0;
  193.      char *verbVector[100];
  194.      ListItem *item = 0;
  195.      void *result = 0;
  196.      char *rest = 0;
  197.  
  198.      MidasTokenizeCommand(command,verbVector,&verbCount,
  199.                           XtNumber(verbVector),delimiters);
  200.  
  201.      for (i=0; i < verbCount; i++)
  202.        {
  203.          char *c , *token = XtNewString(verbVector[i]);
  204.  
  205.          for (c=token ; *c != '\0' ; c++ ) *c = toupper(*c);
  206.  
  207.          item = MidasFindItemInList(CList,token);
  208.          XtFree(token);
  209.  
  210.          if (item != 0) 
  211.            {
  212.              ConvertLink *cl = item->Pointer;
  213.              CList = cl->CList;
  214.            }
  215.          else
  216.            {
  217.              for (item = CList->First; item != 0; item = item->Next )
  218.                {
  219.                  ConvertLink *cl = item->Pointer;
  220.                  ConvertBlock *ab = cl->CLink;
  221.                  char *entry = item->Entry;
  222.                  Boolean indirect = (*entry == '&');
  223.  
  224.                  if (indirect) entry++;
  225.                 
  226.                  if (ab != 0)
  227.                    {
  228.                      MidasOperand Temp;
  229.                      if (strcmp("...",item->Entry+strlen(entry)-3))
  230.                        {
  231.                          if (*entry == '*')
  232.                            {
  233.                              Temp.Value.P = verbVector[i];
  234.                              if (*Temp.Value.P == '"')
  235.                                {
  236.                                  Temp.Value.P++;
  237.                                  *(Temp.Value.P+strlen(Temp.Value.P)-1) = '\0';
  238.                                }
  239.                              Temp.Dynamic = FALSE;
  240.                              Temp.Type = MString;
  241.                            }
  242.                          else Temp = MidasEvaluateExpression(verbVector[i]);
  243.                        }
  244.                      else
  245.                        {
  246.                          rest = MidasRestOfLine(i,verbVector,verbCount);
  247.                          if (*entry == '*')
  248.                            {
  249.                              Temp.Value.P = rest;
  250.                              if (*Temp.Value.P == '"')
  251.                                {
  252.                                  Temp.Value.P++;
  253.                                  *(Temp.Value.P+strlen(Temp.Value.P)-1) = '\0';
  254.                                }
  255.                              Temp.Dynamic = FALSE;
  256.                              Temp.Type = MString;
  257.                            }
  258.                          else Temp = MidasEvaluateExpression(rest);
  259.                          i = verbCount;
  260.                        }
  261. /*
  262.  *                   if (strcmp(ab->FromType,Temp.Type) == 0) ab->ConvertRtn(&Temp); 
  263.  *
  264.  */
  265.                      if (strcmp(ab->ToType,Temp.Type)) MidasConvertOperand(&Temp,ab->ToType);
  266.                      Argv[Argc  ] = Temp;
  267.                      Argi[Argc++] = indirect;
  268.                      CList = cl->CList;
  269.                      break;
  270.                    }
  271.                }
  272.            }
  273.        }
  274.  
  275.      /* Skip optional arguments until end of command */
  276.  
  277.      if (item != 0) 
  278.        {
  279.          for (; (item = MidasFindItemInList(CList,"endofcommand")) == 0;)
  280.            {
  281.              for (item = CList->First; item != 0; item = item->Next )
  282.                if (*item->Entry == '{') 
  283.                  {
  284.                    ConvertLink *cl = item->Pointer;
  285.                    Argv[Argc].Value.I = 0;
  286.                    Argv[Argc].Dynamic = FALSE;
  287.                    Argv[Argc].Type = MInt;
  288.                    Argi[Argc] = FALSE;
  289.                    Argc++;
  290.                    CList = cl->CList;
  291.                    break;    
  292.                  }
  293.              if (item == 0) MidasError("Premature end of command found");
  294.            }
  295.        }
  296.      if (item == 0) 
  297.        {
  298.          for (i=0; i<Argc; i++) if (Argv[i].Dynamic) XtFree((char *)Argv[i].Value.P);
  299.          MidasError("Syntax error in expression");
  300.        }
  301.      *ArgC = Argc;
  302.      return item->Pointer;
  303. }
  304. MidasOperand MidasCallFunction(in)
  305.      char **in;
  306. {
  307.      MidasOperand result;
  308.      if (setjmp(JmpEnv[NumJump++]) == 0)
  309.        {
  310.          char buffer[2000];
  311.          char *p = *in, *q = buffer;
  312.          int n=0 , m=0;
  313.          for (; *p != '\0'; p++)
  314.            {
  315.              *q = *p;
  316.              if      (*p == '"') m = !m;
  317.              else if (!m && *p == '(') { if (++n == 1) *q = ' '; }
  318.              else if (!m && *p == ')') { if (--n == 0) break;    }
  319.              q++;
  320.            }
  321.          if (n != 0) MidasError("Parentheses error in expression: %s",*in+1);
  322.          if (m != 0) MidasError("Mismatched quotes in expression: %s",*in+1);
  323.          *q = '\0';
  324.          {
  325.            MidasOperand Argv[10];
  326.            Boolean Argi[10];
  327.            int Argc, i;
  328.  
  329.            ActionBlock *ab = MidasPrepareToDispatch(&FunctionList,buffer," ,",Argv,Argi,&Argc);
  330.            MidasOperand (*routine)() = (MidasOperand (*)()) ab->ActionRtn; 
  331.            int A[10];
  332.            for (i=0; i<Argc; i++) 
  333.              if (Argi[i]) A[i]=(int) &Argv[i].Value.I;
  334.              else         A[i]=Argv[i].Value.I;
  335.  
  336.  
  337.            switch (Argc)
  338.              {
  339.                case  0: result = routine();
  340.                         break;
  341.                case  1: result = routine(A[0]);
  342.                         break;
  343.                case  2: result = routine(A[0],A[1]);
  344.                         break;
  345.                case  3: result = routine(A[0],A[1],A[2]);
  346.                         break;
  347.                case  4: result = routine(A[0],A[1],A[2],A[3]);
  348.                         break;
  349.                case  5: result = routine(A[0],A[1],A[2],A[3],A[4]);
  350.                         break;
  351.                case  6: result = routine(A[0],A[1],A[2],A[3],A[4],A[5]);
  352.                         break;
  353.                case  7: result = routine(A[0],A[1],A[2],A[3],A[4],A[5],A[6]);
  354.                         break;
  355.                case  8: result = routine(A[0],A[1],A[2],A[3],A[4],A[5],A[6],A[7]);
  356.                         break;
  357.                case  9: result = routine(A[0],A[1],A[2],A[3],A[4],A[5],A[6],A[7],A[8]);
  358.                         break;
  359.                case 10: result = routine(A[0],A[1],A[2],A[3],A[4],A[5],A[6],A[7],A[8],A[9]);
  360.            }
  361.            for (i=0; i<Argc; i++) if (Argv[i].Dynamic) XtFree((char *)Argv[i].Value.P);
  362.          }
  363.          *in = p;
  364.          NumJump--;
  365.        }
  366.      else
  367.        {
  368.          MidasError("Error invoking function: %s",*in);
  369.        }
  370.   return result;
  371. }
  372. static List *MidasFindCommandQualifiers(QL,command)
  373. List *QL;
  374. char *command;
  375.   char *p, *q, *r, delim;
  376.   int Quotes = 0, paren = 0;
  377.   ListItem *item;
  378.   ListItem *new;
  379.   List *CurrentQualifierList = MidasCreateEmptyList("CurrentQualifiers");
  380.  
  381.   for (p=command; *p != '\0'; p++)
  382.     if (*p == '"') Quotes = 1 - Quotes;
  383.     else if (!Quotes && *p == '(') paren++;
  384.     else if (!Quotes && *p == ')') paren--; 
  385.     else if (!Quotes && paren == 0 && *p == ':')
  386.       {
  387.         for (q = p+1 ; *q != ' ' && *q != ':' && *q != '=' && *q != '\0'; q++)
  388.           *q = toupper(*q);
  389.  
  390.         delim = *q;
  391.         *q = '\0';
  392.  
  393.         item = MidasFindItemInList(QL,p+1);
  394.         if (item == 0) MidasError("Unrecognized qualifier %s",p+1);
  395.  
  396.         new = MidasAddItemToList(CurrentQualifierList,p+1);
  397.  
  398.         if (delim == '=')
  399.           {
  400.             MidasOperand *Temp = XtNew(MidasOperand);
  401.             for (r = q + 1; *r != ':' && *r != '\0' && *r != ' '; r++);
  402.             delim = *r;
  403.             *r = '\0';
  404.             new->Pointer = Temp;
  405.             Temp->Type = MString;
  406.             Temp->Dynamic = TRUE;
  407.             Temp->Value.P = (XtPointer) XtNewString(q+1);
  408.           }
  409.         else 
  410.           {
  411.             r = q;
  412.             new->Pointer = 0;
  413.           }
  414.         for (; p < r ; p++) *p=' ';
  415.         *p = delim;
  416.         p--;
  417.       }
  418.   return CurrentQualifierList;
  419. }
  420. void MidasDispatchCommand(command)
  421.      char *command;
  422. {
  423.      char *p;
  424.      char *buffer = XtNewString(command);
  425.      List *QL = 0;
  426.      ListItem *item;  
  427.  
  428.      if (setjmp(JmpEnv[NumJump++]) == 0)
  429.        {
  430.          QL = MidasFindCommandQualifiers(&QualifierList,buffer);
  431.          *++CurrentQualifierList = QL;
  432.          {
  433.            MidasOperand Argv[10];
  434.            Boolean Argi[10];
  435.            int Argc, i;
  436.            ActionBlock *ab = MidasPrepareToDispatch(&TopLevelCommandList,buffer," ",Argv,Argi,&Argc);
  437.            int A[10];
  438.            for (i=0; i<Argc; i++) 
  439.              if (Argi[i]) A[i]=(int) &Argv[i].Value.I;
  440.              else         A[i]=Argv[i].Value.I;
  441.  
  442.            switch (Argc)
  443.              {
  444.                case  0: ab->ActionRtn();
  445.                         break;
  446.                case  1: ab->ActionRtn(A[0]);
  447.                         break;
  448.                case  2: ab->ActionRtn(A[0],A[1]);
  449.                         break;
  450.                case  3: ab->ActionRtn(A[0],A[1],A[2]);
  451.                         break;
  452.                case  4: ab->ActionRtn(A[0],A[1],A[2],A[3]);
  453.                         break;
  454.                case  5: ab->ActionRtn(A[0],A[1],A[2],A[3],A[4]);
  455.                         break;
  456.                case  6: ab->ActionRtn(A[0],A[1],A[2],A[3],A[4],A[5]);
  457.                         break;
  458.                case  7: ab->ActionRtn(A[0],A[1],A[2],A[3],A[4],A[5],A[6]);
  459.                         break;
  460.                case  8: ab->ActionRtn(A[0],A[1],A[2],A[3],A[4],A[5],A[6],A[7]);
  461.                         break;
  462.                case  9: ab->ActionRtn(A[0],A[1],A[2],A[3],A[4],A[5],A[6],A[7],A[8]);
  463.                         break;
  464.                case 10: ab->ActionRtn(A[0],A[1],A[2],A[3],A[4],A[5],A[6],A[7],A[8],A[9]);
  465.            }
  466.            for (i=0; i<Argc; i++) if (Argv[i].Dynamic) XtFree((char *) Argv[i].Value.P);
  467.          }
  468.        for (item = QL->First; item != 0; item = item->Next)
  469.          {
  470.            MidasOperand *Temp = item->Pointer;
  471.            if (Temp != 0 && Temp->Dynamic) XtFree((char *) Temp->Value.P);
  472.          }
  473.        MidasDestroyList(*CurrentQualifierList--);
  474.        XtFree(buffer);
  475.        NumJump--;
  476.        }
  477.      else
  478.        {
  479.          if (QL != 0) 
  480.            {  
  481.              for (item = QL->First; item != 0; item = item->Next)
  482.                {
  483.                  MidasOperand *Temp = item->Pointer;
  484.                  if (Temp != 0 && Temp->Dynamic) XtFree((char *) Temp->Value.P);
  485.                }
  486.              MidasDestroyList(*CurrentQualifierList--);
  487.            } 
  488.          XtFree(buffer);
  489.          MidasError("Illegal command");
  490.        }
  491. }
  492. Boolean MidasGetQualifier(Qualifier,Result)
  493. char *Qualifier;
  494. XtPointer *Result;
  495. {
  496.    ConvertBlock *ab;
  497.    ListItem *qitem, *item;
  498.  
  499.    if (*CurrentQualifierList == 0) return FALSE;
  500.  
  501.    item = MidasFindItemInList(*CurrentQualifierList, Qualifier);
  502.    if (item == 0) return FALSE;
  503.  
  504.    qitem = MidasFindItemInList(&QualifierList,Qualifier);
  505.    ab = qitem->Pointer;
  506.    if (ab != 0) 
  507.      { 
  508.        MidasOperand *Temp = item->Pointer;
  509. /*
  510.  * Speed up temporarily removed.   
  511.  *      if (strcmp(Temp->Type,ab->FromType) == 0) ab->ConvertRtn(Temp);
  512.  *
  513.  */
  514.        if (strcmp(Temp->Type,ab->ToType)) MidasConvertOperand(Temp,ab->ToType);
  515.        *Result = Temp->Value.P; 
  516.      }
  517.    return TRUE;
  518. }
  519. void MidasSetQualifier(Qualifier,Value)
  520. char *Qualifier;
  521. char *Value;
  522. {
  523.    ActionBlock *ab;
  524.    ListItem *qitem, *item;
  525.  
  526.    if (*CurrentQualifierList == 0) 
  527.      *CurrentQualifierList = MidasCreateEmptyList("CurrentQualifiers");   
  528.  
  529.    item = MidasFindItemInList(*CurrentQualifierList, Qualifier);
  530.    if (item == 0)
  531.      {
  532.        item = MidasAddItemToList(*CurrentQualifierList, Qualifier);
  533.      }
  534.    else
  535.      {
  536.        if (item->Pointer != 0) XtFree(item->Pointer);
  537.      }
  538.  
  539.    if (Value == NULL) item->Pointer = NULL;
  540.    else 
  541.      {
  542.        MidasOperand *Operand = XtNew(MidasOperand);
  543.        item->Pointer = Operand;
  544.        Operand->Type = MString;
  545.        Operand->Dynamic = TRUE;
  546.        Operand->Value.P = (XtPointer) XtNewString(Value);
  547.      }
  548. }
  549.